#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include "cJSON.h"
#include <stdbool.h>
#define N 64
int main(int argc, char const *argv[])
{
	int broadfd;
	//创建一个socket文件描述符
	broadfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (broadfd < 0)
	{
		perror("sock err");
		return -1;
	}
	//绑定套接字(ip+port)
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8887); //端口号
	addr.sin_addr.s_addr = INADDR_ANY;
	int addrlen = sizeof(addr);
	if (bind(broadfd, (struct sockaddr *)&addr, addrlen) < 0)
	{
		perror("bind err");
		return -1;
	}
	ssize_t len;
	char buf[N] = {0};
	struct sockaddr_in cliaddr, caddr;
	//接收"hello"搜索包
	bzero(buf, N);
	len = recvfrom(broadfd, buf, N, 0, (struct sockaddr *)&cliaddr, &addrlen);
	//判断是否是本公司产品：收到的数据是否"hello"
	if (strcmp(buf, "hello") != 0)
	{
		printf("not my hello\n");
		return -1;
	}
	//回复OK，告诉软件，我收到了搜索协议，并且回复地址
	sendto(broadfd, "OK", 3, 0, (struct sockaddr *)&cliaddr, addrlen);
	//变身为TCP服务器，准备接收软件的升级文件
	int tcpfd = socket(AF_INET, SOCK_STREAM, 0);
	if (tcpfd < 0)
	{
		perror("sock err");
		return -1;
	}
	if (bind(tcpfd, (struct sockaddr *)&addr, addrlen) < 0)
	{
		perror("bind err");
		return -1;
	}
	//监听套接字
	if (listen(tcpfd, 6) < 0)
	{
		perror("listen err");
		return -1;
	}
	//接收客户端的连接
	printf("wait client connect\n");
	int clifd;
	socklen_t len1 = sizeof(caddr);
	clifd = accept(tcpfd, (struct sockaddr *)&caddr, &len1);
	if (clifd < 0)
	{
		perror("accept err");
		return -1;
	}
	printf("成功连接TCP\n");
	char buf2[3000] = {0};
	char buf3[] = "no";
	char buf4[] = "living";
	size_t recvbyte;
	while (1)
	{
		recvbyte = recv(clifd, buf2, sizeof(buf2), 0);
		if (recvbyte < 0)
		{
			perror("recv error\n");
			break;
		}
		cJSON *root = cJSON_Parse(buf2);
		cJSON *item = cJSON_GetObjectItem(root, "type");
		int type = item->valueint;
		if (type == 1)
		{
			//查看是否拥有点表文件
			int fd = open("./datapot.json", O_RDONLY | O_WRONLY);
			//如果没有点表
			if (fd < 0)
			{
				fd = open("./datapot.json", O_RDONLY | O_WRONLY | O_CREAT, 0666);
				//没有datapot.json点表文件需要qt传点表，序列化json
				//创建root根节点
				cJSON *root = cJSON_CreateObject();
				//创建节点并添加到根节点中
				cJSON_AddNumberToObject(root, "type", 1);
				cJSON_AddNumberToObject(root, "result", 0);
				cJSON_AddBoolToObject(root, "up_config", true);
				//将json发送给qt
				char *p = cJSON_Print(root);
				p[strlen(p)] = '\0';
				send(clifd, p, strlen(p), 0);
				//接收qt发送来的点表文件，创建datapot.json
				int recvsize = 0;
				while ((recvsize = recv(clifd, buf2, sizeof(buf2), 0)) > 0)
				{
					write(fd, buf2, recvsize);
					memset(buf2, 0, sizeof(buf2));
				}
				close(fd);
				cJSON_Delete(root);
				free(p);
			}
			//有点表
			else
			{
				//创建root根节点
				cJSON *root = cJSON_CreateObject();
				//有点表文件不需要qt传点表
				cJSON_AddNumberToObject(root, "type", 1);
				cJSON_AddNumberToObject(root, "result", 0);
				cJSON_AddBoolToObject(root, "up_config", false);
				//将json发送给qt
				char *p = cJSON_Print(root);
				send(clifd, p, strlen(p), 0);
				cJSON_Delete(root);
				free(p);
			}
		}
		//心跳检测
		else if (type == 3)
		{
			recvbyte = recv(clifd, buf2, sizeof(buf2), 0);
			if (recvbyte < 0)
			{
				break;
			}
			send(clifd, buf4, strlen(buf4), 0);
			memset(buf2, 0, sizeof(buf2));
		}
	}
	close(clifd);
	// 5.关闭套接字（close）
	close(broadfd);
	return 0;
}